package com.ruoyi.web.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.framework.web.enums.AbnormalEnum;
import com.ruoyi.framework.web.exception.TadpoleException;
import com.ruoyi.web.domain.LegalTender;
import com.ruoyi.web.domain.QgPayBusiness;
import com.ruoyi.web.domain.QgPayRechargeDetail;
import com.ruoyi.web.dto.QgPayRechargeDetailAddDTO;
import com.ruoyi.web.enums.QGPayRechargeDetailEnum;
import com.ruoyi.web.mapper.QgPayRechargeDetailMapper;
import com.ruoyi.web.mapper.UserCapitalMapper;
import com.ruoyi.web.service.IAppUserService;
import com.ruoyi.web.service.IQgPayRechargeDetailService;
import com.ruoyi.web.utils.CommonUtil;
import com.ruoyi.web.utils.RedisCacheUtil;
import com.ruoyi.web.utils.qg_pay.client.QGPayHttpClient;
import com.ruoyi.web.utils.qg_pay.config.QGPayConfig;
import com.ruoyi.web.utils.qg_pay.entity.QGPayCommonRequestParam;
import com.ruoyi.web.utils.qg_pay.entity.QGPayCommonResponse;
import com.ruoyi.web.utils.qg_pay.entity.request.QGPayOrderPay;
import com.ruoyi.web.utils.qg_pay.entity.response.QGPayOrderPayRes;
import com.ruoyi.web.utils.qg_pay.utils.QGPayUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * QGPay充值明细Service业务层处理
 *
 * @date 2023-03-15
 */
@Slf4j
@Service
@AllArgsConstructor
public class QgPayRechargeDetailServiceImpl implements IQgPayRechargeDetailService {
    private final QgPayRechargeDetailMapper qgPayRechargeDetailMapper;
    private final QGPayConfig qgPayConfig;
    private final CommonUtil commonUtil;
    private final QGPayUtil qgPayUtil;
    private final QGPayHttpClient qgPayHttpClient;
    private final RedisCacheUtil redisCacheUtil;
    private final UserCapitalMapper userCapitalMapper;
    private final IAppUserService appUserService;

    /**
     * 查询QGPay充值明细
     *
     * @param id QGPay充值明细主键
     * @return QGPay充值明细
     */
    @Override
    public QgPayRechargeDetail selectQgPayRechargeDetailById(Long id) {
        return qgPayRechargeDetailMapper.selectQgPayRechargeDetailById(id);
    }

    /**
     * 查询QGPay充值明细列表
     *
     * @param qgPayRechargeDetail QGPay充值明细
     * @return QGPay充值明细
     */
    @Override
    public List<QgPayRechargeDetail> selectQgPayRechargeDetailList(QgPayRechargeDetail qgPayRechargeDetail) {
        List<QgPayRechargeDetail> list = qgPayRechargeDetailMapper.selectQgPayRechargeDetailList(qgPayRechargeDetail);

        // 遍历
        list.forEach(i -> {
            // 设置字典项
            i.setStatus(QGPayRechargeDetailEnum.Status.findName(i.getStatus()));
        });

        return list;
    }

    /**
     * 创建支付
     *
     * @param dto dto
     * @return {@link AjaxResult}
     * @since 2023/3/15 17:32
     */
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public String add(QgPayRechargeDetailAddDTO dto) {
        SysUser user = CommonUtil.getLoginUserNotNull();
        // 根据法币编码查询法币
        LegalTender legalTender = redisCacheUtil.getLegalTender(dto.getLegalTenderCode(), false);
        // 根据业务编码查询QGPay业务
        QgPayBusiness qgPayBusiness = redisCacheUtil.getQgPayBusiness(dto.getBusinessCode(), false);

        // 创建充值记录
        QgPayRechargeDetail detail = new QgPayRechargeDetail();
        detail.setUserId(user.getUserId());
        detail.setLegalTenderName(legalTender.getName());
        detail.setLegalTenderCode(legalTender.getCode());
        detail.setBusinessName(qgPayBusiness.getName());
        detail.setBusinessCode(qgPayBusiness.getCode());
        detail.setAmount(dto.getAmount());
        detail.setRate(legalTender.getRate());
        detail.setUsdt(QGPayUtil.transferLegalTender2USDT(detail.getAmount(), detail.getRate()));
        detail.setStatus(QGPayRechargeDetailEnum.Status.UNDO.getValue());
        commonUtil.initCreateAbout(detail, user);

        // 如果转换为usdt后数量等于0
        if (detail.getUsdt().compareTo(BigDecimal.ZERO) == 0) {
            throw new TadpoleException(AbnormalEnum.MSG.FAILED_TO_CREATE_PAYMENT_ORDER);
        }
        if (qgPayRechargeDetailMapper.insertQgPayRechargeDetail(detail) != 1) {
            throw new TadpoleException(AbnormalEnum.MSG.FAILED_TO_CREATE_PAYMENT_ORDER);
        }

        try {
            // 创建代收订单
            QGPayOrderPay body = new QGPayOrderPay();
            body.setMerchant(qgPayConfig.getMerchant());
            body.setOrderNo(commonUtil.getId());
            body.setBusinessCode(dto.getBusinessCode());
            body.setName("test");
            body.setPhone("15112345678");
            body.setEmail("15112345678@163.com");
            body.setAmount(dto.getAmount());
            body.setNotifyUrl(qgPayConfig.getReceiveNotifyUrl());
            body.setPageUrl(qgPayConfig.getReceiveSuccessBaseUrl());
            body.setBankCode(QGPayUtil.getBankCodeWhenReceive(dto.getLegalTenderCode(), dto.getBusinessCode()));
            body.setSubject("none");
            QGPayCommonRequestParam<?, QGPayOrderPay> param = new QGPayOrderPay();
            param.setBody(body);
            QGPayCommonResponse<QGPayOrderPayRes> res = qgPayHttpClient.request(param);
            if (!res.getIsSuccess()) {
                log.error("QGPay创建代收订单失败，请求参数：{}，返回结果：{}", param.getBody(), res);
                throw new TadpoleException();
            }

            return res.getData().getOrderData();

        } catch (Throwable e) {
            log.error(e.getMessage());
            throw new TadpoleException(AbnormalEnum.MSG.FAILED_TO_CREATE_PAYMENT_ORDER);
        }
    }

    /**
     * QGPay代收通知
     *
     * @param dto 通知
     * @since 2023/3/17 14:21
     */
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void qgOrderPayNotify(JSONObject dto) {
        // 校验通知参数
        qgPayUtil.validNotify(dto);

        QgPayRechargeDetail condition = new QgPayRechargeDetail();
        condition.setId(dto.getLongValue("merchantOrderNo"));
        QgPayRechargeDetail detail = qgPayRechargeDetailMapper.getOneLock(condition);
        // 判断充值明细状态，不是未支付状态时，直接结束，返回SUCCESS
        if (Objects.isNull(detail) || !QGPayRechargeDetailEnum.Status.UNDO.getValue().equals(detail.getStatus())) {
            return;
        }

        boolean isSuccess = "success".equals(dto.getString("status"));
        // 支付成功
        if (isSuccess) {
            BigDecimal payAmount = dto.getBigDecimal("payAmount");
            // 根据法币编码查询法币
            LegalTender legalTender = redisCacheUtil.getLegalTender(detail.getLegalTenderCode(), true);
            // 如果没有查询到法币信息，使用下单时汇率
            BigDecimal actualRate = Objects.isNull(legalTender) ? detail.getRate() : legalTender.getRate();
            BigDecimal actualUsdt = QGPayUtil.transferLegalTender2USDT(payAmount, actualRate);

            detail.setActualAmount(payAmount);
            detail.setActualRate(actualRate);
            detail.setActualUsdt(actualUsdt);
            detail.setStatus(QGPayRechargeDetailEnum.Status.SUCCESS.getValue());

            // 用户资金账户增加额度
            if (userCapitalMapper.addBalance(detail.getUserId(), detail.getActualUsdt()) != 1) {
                qgPayOrderPayHandleFail(dto);
            }

            // 直推分红
            try {
                appUserService.rechargeDistribution(detail.getUserId(), detail.getActualUsdt());
            } catch (Throwable e) {
                qgPayOrderPayHandleFail(dto);
            }

            // 支付失败
        } else {
            detail.setStatus(QGPayRechargeDetailEnum.Status.FAIL.getValue());
        }

        detail.setUpdateTime(new Date());
        if (qgPayRechargeDetailMapper.updateQgPayRechargeDetail(detail) != 1) {
            qgPayOrderPayHandleFail(dto);
        }
    }

    /**
     * 代收回调通知处理失败 统一处理逻辑
     *
     * @param dto 通知
     * @since 2023/3/17 15:05
     */
    private static void qgPayOrderPayHandleFail(Object dto) {
        log.error("代收回调通知处理失败，通知：{}", dto);
        CommonUtil.throwError();
    }

    /**
     * h5分页查询
     *
     * @param condition 查询条件
     * @return {@link List< QgPayRechargeDetail>}
     * @since 2023/3/17 10:51
     */
    @Override
    public List<QgPayRechargeDetail> appPage(QgPayRechargeDetail condition) {
        SysUser user = CommonUtil.getLoginUserNotNull();
        condition.setUserId(user.getUserId());
        List<QgPayRechargeDetail> list = qgPayRechargeDetailMapper.selectQgPayRechargeDetailList(condition);

        // 遍历
        list.forEach(i -> {
            // 设置字典项
            i.setStatus(QGPayRechargeDetailEnum.Status.findName(i.getStatus()));
        });

        return list;
    }
}
